// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.aop;

import com.liuxinlong.annotation.LogAnnotation;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.modules.common.controller.response.BaseResp;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.entity.UserLog;
import com.liuxinlong.modules.log.service.UserLogService;
import com.liuxinlong.modules.system.controller.request.UserLoginReq;
import com.liuxinlong.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 系统日志:切面处理类
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年2月25日
 */
@Component
@Slf4j
@Aspect
public class LogAnnotationAspect {
    @Autowired
    private UserLogService userLogService;

    @Autowired
    private UserDao userDao;
    /**
     * 定义切点 @Pointcut
     * 在注解的位置切入代码
     */
    @Pointcut("@annotation( com.liuxinlong.annotation.LogAnnotation)")
    public void logPointCut() {
    }

    /**
     * 设置操作异常切入点记录异常日志 扫描所有包下操作
     *
     */
    @Pointcut("execution(* com.liuxinlong..*.*(..))")
    public void exceptionLogPointCut() {
    }

    /**
     * 切面 配置通知
     *
     * @param joinPoint joinPoint
     * @return 返回体
     * @throws Throwable 异常信息
     */
    @Around("logPointCut()")
    public Object saveUserLog(ProceedingJoinPoint joinPoint) throws Throwable {

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //IP地址
        String ipAddr = getRemoteHost(request);
        //保存日志
        UserLog userLog = new UserLog();
        userLog.setIp(ipAddr);

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取操作
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
        if (logAnnotation != null) {
            String value = logAnnotation.value();
            String business = logAnnotation.business();
            userLog.setOperateType(logAnnotation.operateType());
            userLog.setContent(value);//保存获取的操作
            userLog.setBusiness(business);
        }

        //获取请求的类名
//        String className = joinPoint.getTarget().getClass().getName();
//        //获取请求的方法名
//        String methodName = method.getName();
//        userLog.setBusiness(className + "." + methodName);

        //请求的参数
        Object[] args = joinPoint.getArgs();
        //将参数所在的数组转换成json
//        String params = JSON.toJSONString(args);
//        userLog.setContent(params);

        Date current = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        userLog.setOperateTime(sdf.format(current));
        //获取用户名
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (ObjectUtils.isEmpty(currentUser) && args.length > 0 && args[0] instanceof UserLoginReq) {
            UserLoginReq req = (UserLoginReq) args[0];
            String userAccount = req.getUsername();
            User loginUser =  userDao.getUserByAccount(userAccount);
            if (ObjectUtils.isEmpty(loginUser)) {
                userLog.setOperateUser("");
            } else {
                userLog.setOperateUser(loginUser.getId());
            }
        } else {
            userLog.setOperateUser(currentUser.getId());
        }

//        //获取用户ip地址
//        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//        userLog.setIp(IPUtils.getIpAddr(request));
        //这里就是开始执行方法 然后拿到返回值
        Object result = joinPoint.proceed();
        if (ObjectUtils.isEmpty(result)) {
            userLog.setOperateResult("成功");
        } else {
            String message = ((BaseResp) result).getRetMessage();
            userLog.setOperateResult(message);
        }

        //调用service保存userLog实体类到数据库
        userLogService.addUserLog(userLog);
        return result;
    }

    /**
     * 异常返回通知，用于拦截异常日志信息 连接点抛出异常后执行
     */
//    @AfterThrowing(pointcut = "exceptionLogPointCut()", throwing = "e")
//    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        //IP地址
//        String ipAddr = getRemoteHost(request);
//        //保存日志
//        UserLog userLog = new UserLog();
//        userLog.setIp(ipAddr);
//
//        //从切面织入点处通过反射机制获取织入点处的方法
//        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//        //获取切入点所在的方法
//        Method method = signature.getMethod();
//
//        //获取操作
//        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
//        if (logAnnotation != null) {
//            String value = logAnnotation.value();
//            String business = logAnnotation.business();
//            userLog.setOperateType(logAnnotation.operateType());
//            userLog.setContent(value);//保存获取的操作
//            userLog.setBusiness(business);
//        }
//        //请求的参数
//        Object[] args = joinPoint.getArgs();
//
//        Date current = new Date();
//        SimpleDateFormat sdf = new SimpleDateFormat(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
//        userLog.setOperateTime(sdf.format(current));
//        //获取用户名
//        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
//        if (ObjectUtils.isEmpty(currentUser) && args.length > 0 && args[0] instanceof UserLoginReq) {
//            UserLoginReq req = (UserLoginReq) args[0];
//            String userAccount = req.getUsername();
//            User loginUser =  userDao.getUserByAccount(userAccount);
//            if (ObjectUtils.isEmpty(loginUser)) {
//                userLog.setOperateUser("");
//            } else {
//                userLog.setOperateUser(loginUser.getId());
//            }
//        } else {
//            userLog.setOperateUser(currentUser.getId());
//        }
//
//        //这里就是开始执行方法 然后拿到返回值
//        if (e instanceof AosException) {
//            String message = ((AosException) e).getErrorMsg();
//            userLog.setOperateResult(message);
//        } else {
//            userLog.setOperateResult(e.getMessage());
//        }
//
//        //调用service保存userLog实体类到数据库
//        userLogService.addUserLog(userLog);
//
//    }


    /**
     * 获取目标主机的ip
     *
     * @param request 请求信息
     * @return 目标主机ip
     */
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}
